import __DB__       from '../db/index.js';
import __canvas__   from '../canvas/index.js';
import __tool__     from '../tool/index.js';

class formateClass {
    constructor(){
        this.nodesMany          = [];
        this.nodesManyFree      = [];
        this.onceActive         = 0;// 只执行一次
        // __DB__.nodesManyIds     = {}; // 节点的子节点ID列表
    }

    init(items){
        this.otm(items);                    // 数据解析-生成节点树
        this.node_maxh(this.nodesMany);     // 解析节点 计算出节点的最大高
        this.node_maxw(this.nodesMany);     // 解析节点 计算出节点的最大宽
        this.node_poi(this.nodesMany);      // 解析节点 计算出需要的坐标
        this.node_pull(this.nodesMany);     // 解析节点 计算出展开收起按钮的位置

        if(this.nodesManyFree.length > 0){
            this.node_maxh(this.nodesManyFree);     // 解析节点 计算出节点的最大高
            this.node_maxw(this.nodesManyFree);     // 解析节点 计算出节点的最大宽
            this.node_poi(this.nodesManyFree);      // 解析节点 计算出需要的坐标
            this.node_pull(this.nodesManyFree);     // 解析节点 计算出展开收起按钮的位置
        }

        // if(this.onceActive === 0){
        //     this.onceActive++;
        
        if(this.onceActive === 0){
            this.onceActive++;
            // 节点层级-左右
            setNodeGroup(this.nodesMany);
            function setNodeGroup(items){
                let arr_l = __tool__.deepCopy(items);
                let arr_r = __tool__.deepCopy(items);
                let group = {
                    l:0,
                    r:0
                };

                while(arr_l.length > 0){
                    if(!arr_l[0].root)group.l++;
                    [...arr_l].forEach(child=>{
                        // __DB__.get(child.id).group = group.l;
                        arr_l.shift();
                        
                        if(child.id === 'root'){
                            arr_l.push(...child.node.childrenRoot.flip);
                        }
                        else{
                            arr_l.push(...child.node.children);
                        }
                    });
                }

                while(arr_r.length > 0){
                    if(!arr_r[0].root)group.r++;
                    [...arr_r].forEach(child=>{
                        // __DB__.get(child.id).group = group.r;
                        arr_r.shift();
                        
                        if(child.id === 'root'){
                            arr_r.push(...child.node.childrenRoot.unFlip);
                        }
                        else{
                            arr_r.push(...child.node.children);
                        }
                    });
                }

                
                __DB__.get('root').nodeGroup = group;
            }

            // 节点层级-最大值和每一层
            setNodeGroup2(this.nodesMany);
            function setNodeGroup2(items){
                let arr = __tool__.deepCopy(items)
                let num = 0;
                while(arr.length > 0){

                    num++;
                    [...arr].forEach(child=>{
                        __DB__.get(child.id).group = num;
                        arr.shift();
                        
                        if(child.id === 'root'){
                            arr.push(...child.node.childrenRoot.flip);
                            arr.push(...child.node.childrenRoot.unFlip);
                        }
                        else{
                            arr.push(...child.node.children);
                        }
                    });
                }
            
                __DB__.get('root').maxGroup = num;
            }
        }
        this.node_maxh(this.nodesMany);     // 解析节点 计算出节点的最大高
        this.node_maxw(this.nodesMany);     // 解析节点 计算出节点的最大宽
        this.node_poi(this.nodesMany);      // 解析节点 计算出需要的坐标
        this.node_pull(this.nodesMany);     // 解析节点 计算出展开收起按钮的位置

            /*
                setNodeGroup(this.nodesMany);
                function setNodeGroup(items){
                    let arr = __tool__.deepCopy(items)
                    let num = 0;
                    while(arr.length > 0){

                        num++;
                        [...arr].forEach(child=>{
                            __DB__.get(child.id).group = num;
                            arr.shift();
                            
                            if(child.id === 'root'){
                                arr.push(...child.node.childrenRoot.flip);
                                arr.push(...child.node.childrenRoot.unFlip);
                            }
                            else{
                                arr.push(...child.node.children);
                            }
                        });
                    }
                

                    __DB__.get('root').maxGroup = num;
                }
            */
        // }
        if(this.nodesManyFree.length > 0){
            this.node_maxh(this.nodesManyFree);     // 解析节点 计算出节点的最大高
            this.node_maxw(this.nodesManyFree);     // 解析节点 计算出节点的最大宽
            this.node_poi(this.nodesManyFree);      // 解析节点 计算出需要的坐标
            this.node_pull(this.nodesManyFree);     // 解析节点 计算出展开收起按钮的位置
        }

        
    }

    // 节点数据模板
    nodeDataModel(item){
        let nodeType = item.nodeType||"rule";// 显示类型

        // 节点宽度
        let nodeLimit = item.nodeLimit;                     // 自定义宽度
        if(!item.nodeLimit && item.root)nodeLimit=200;
        let publicLimit = __DB__.publicData.nodeLimit;      // 初始默认宽度
        let styleLimit = item.style?item.style.limit:null;  // 目前已有宽度
        if(nodeLimit){
            nodeLimit = nodeLimit;
        }
        else if(styleLimit){
            nodeLimit = styleLimit
        }
        else{
            nodeLimit = publicLimit
        }

        let pull = {
            l:{
                show:null,
                plus:false,
                has:null,
            },
            r:{
                show:null,
                plus:false,
                has:null,
            }
        }

        if(item.pull){
            pull = {
                l:{...pull.l,...item.pull.l},
                r:{...pull.l,...item.pull.r},
            };
        }
        
        let obj = {
            id                  : item.id,                  // 节点ID
            pid                 : item.pid||null,           // 父节点ID
            root                : item.root||false,         // 是否是根节点
            flip                : item.flip||false,         // 就否反转
            label               : item.label,               // 标题
            type                : item.type||"tree",        // 物理类型
            show                : true,                     // 是否显示
            nodeType            : item.nodeType||"rule",    // 逻辑类型
            html                : item.html||"",            // 自定义额外内容
            data                : item.data||"",            // 自定义数据
            status              : item.status,              // 节点状态-1：无，0：失败，1：进行中，2：成功
            childrenIds         : item.childrenIds||[],     // 节点的子节点ID列表
            divClass            : item.divClass||[],        // 节点的自定义样式
            nodeGroup           : item.nodeGroup||{l:0,r:0},// 节点层级数
            maxGroup            : item.maxGroup||null,      // 节点层级数
            group               : item.group||null,         // 节点层级数
            divColor            : item.divColor||"",        // 自定义字体颜色
            divBgColor          : item.divBgColor||"",      // 自定义背景字体颜色
            // 是否展开
            pull,

            offset              : item.offset||{x:null,y:null},          // 距离root的偏移量，应对不同分辨率下自由节点的位置问题，自由节点的位置由根节点减去偏移量获取

            // 图谱私有属性，不对外暴露
            style               : {
                icon            : __canvas__.nodeStyleInit[nodeType].icon||"",  // 节点图标
                cls             : __canvas__.nodeStyleInit[nodeType].cls||"",   // 图标样式
                limit           : nodeLimit,                                    // 节点宽度
                priority        : item.priority||1,                             // 优先级
            },

            // 图谱私有属性，不对外暴露
            node                : {
                index               : null,                 // 节点索引
                indexMany           : [],                   // 节点索引（无限级）
                children            : [],                   // 子节点集
                childrenRoot        : {                     // 根节点的子节点集
                    flip     : [],                          // 反转子节点集
                    unFlip   : [],                          // 默认子节点集
                },
                
                // 各项配置：宽、高、坐标、最大值等
                init                : {
                    poi     : item.init?item.init.poi:{x:0,y:0},                             // 坐标
                    point   : {a:[],b:[],c:[],d:[],ab:[],bc:[],cd:[],ad:[],mid:[]},          // 周围八个点
                    size    : {w:0,h:0},                                                     // 尺寸
                    max     : {top:0,h:0,w:0,ch:0},                                          // h是包括节点自己的最大高，ch是除了自己所有子节点的最大高
                    maxRoot : {
                        l : {top:0,h:0,w:0,ch:0},                                            // h是包括节点自己的最大高，ch是除了自己所有子节点的最大高
                        r : {top:0,h:0,w:0,ch:0},                                            // h是包括节点自己的最大高，ch是除了自己所有子节点的最大高
                    },
                },

                
            },
        };

        if(item.node && item.node.init){
            if(item.node.init.poi)obj.node.init.poi = {...obj.node.init.poi,...item.node.init.poi};
        }

        return obj;
    }

    // 数据解析-生成节点树
    otm(items){
        let nodes = items;

        let rootData = __DB__.get('root');
        this.nodesManyFree = nodes.filter(el=>{
            if(el.type === 'free'){
                let nodeId = el.id;
                let nodeEl = document.getElementById(nodeId);

                let offset = el.offset;
                if(offset.x === null || offset.y === null){
                    console.info(`自由节点${el.label}的偏移量有问题`,el);
                    return true;
                }
                let root_x = rootData.node.init.poi.x;
                let root_y = rootData.node.init.poi.y;
                let x = root_x - offset.x;
                let y = root_y - offset.y;
                el.node.init.poi.x = x;
                el.node.init.poi.y = y;
                
                nodeEl.style.left = x + "px";
                nodeEl.style.top  = y + "px";

                let itemPoi = __tool__.idTrunPoi(el.id);
                el.node.init.point = itemPoi.point;
            }
            return el.type === 'free';
        });

        let nodesMany = nodes.map((el,i)=>{
            let hasRootLeft = false;
            let childrenFilp = nodes.filter(item => {
                let sign = item.pid === el.id && item.flip && !el.pull.l.plus;
                if(!hasRootLeft)hasRootLeft = item.pid === el.id && item.flip;
                return sign;
            });

            let hasRootRight = false;
            let childrenUnFlip = nodes.filter(item => {
                let sign = item.pid === el.id && !item.flip && !el.pull.r.plus;
                if(!hasRootRight)hasRootRight = item.pid === el.id && !item.flip;
                return sign;
            });

            let hasFilp = false;
            let hasUnFlip = false;
            let children = nodes.filter(item=>{
                if(item.pid === el.id){
                    if(!el.root){
                        if(!el.root)item.flip = el.flip;
                    }
                }

                let plus = el.flip?!el.pull.l.plus:!el.pull.r.plus;

                if(el.flip){
                    if(!hasFilp)hasFilp = item.pid === el.id;
                }
                else{
                    if(!hasUnFlip)hasUnFlip = item.pid === el.id;
                }

                
                return item.pid === el.id && plus;
            });

            if(el.root){
                el.node.childrenRoot = {
                    flip    : childrenFilp,
                    unFlip  : childrenUnFlip,
                }

                el.pull.l.has = hasRootLeft;
                el.pull.r.has = hasRootRight;
            }
            else{
                if(el.nodeType === "node"){el.show = false;}
                el.node.children = children;

                if(el.flip){
                    el.pull.l.has = hasFilp;
                }
                else{
                    el.pull.r.has = hasUnFlip;
                }
            }

            return el;
        });

        this.nodesMany = nodesMany.filter(item=>{
            return item.root;
        });

        // 生成节点的子节点列表
        let charr = {};
        // let nodeGroup = {
        //     l:0,
        //     r:0,
        // };
        selNodeChildren(this.nodesMany);// 树节点
        selNodeChildren(this.nodesManyFree);// 自由节点
        __DB__.nodesManyIds = charr;// 节点的子节点ID列表
        // __DB__.setRootData({nodeGroup});

        // 生成节点的子节点ID列表
        function selNodeChildren(items){
            let total = []
            items.forEach((el,i)=>{
                if(el.root){
                    let oa = selNodeChildren(el.node.childrenRoot.flip);
                    let ob = selNodeChildren(el.node.childrenRoot.unFlip);
                    oa.forEach(ee=>{
                        total.push(ee)
                    })
                    ob.forEach(ee=>{
                        total.push(ee)
                    })
    
                    charr[el.id] = total;
                }
                else{
                    let oc = selNodeChildren(el.node.children);
                    oc.forEach(ee=>{
                        total.push(ee)
                    })
                    total.push(el.id);
                    charr[el.id] = oc;
    
                }
            })
    
            return total;
        }

        

        // function setNodeGroup(items){
        //     let arr = __tool__.deepCopy(items)
        //     let num = 0;
        //     while(arr.length > 0){

        //         num++;
        //         [...arr].forEach(child=>{
        //             __DB__.get(child.id).group = num;
        //             arr.shift();
                    
        //             if(child.id === 'root'){
        //                 arr.push(...child.node.childrenRoot.flip);
        //                 arr.push(...child.node.childrenRoot.unFlip);
        //             }
        //             else{
        //                 arr.push(...child.node.children);
        //             }
        //         });
        //     }

        //     __DB__.get('root').maxGroup = num;
        // }
    }

    // 解析节点 计算出节点的最大高
    node_maxh(items){
        let _this = this;
        recursion(items,null);
        return items;
        function recursion(items,parent){
            let max = {
                l:{w:0,h:0},
                r:{w:0,h:0},
            }
            items.forEach((el,i)=>{
                if(el.root){
                    let rb = null,h = 0,w = 0,maxh = 0,maxw = 0;
                    let root = __DB__.get('root');
                    if(el.node.childrenRoot.flip.length > 0){
                        rb = recursion(el.node.childrenRoot.flip,el);
                        // 最大高
                        maxh = rb.l.h;
                        el.node.init.maxRoot.l.ch = maxh;
                        h = el.node.init.size.h;
                        maxh = h<maxh?maxh:h;
                        el.node.init.maxRoot.l.h = maxh;

                        let mid = el.node.init.point.mid;
                        
                        el.node.init.maxRoot.l.top = mid[1] - maxh/2;
                        
                        root.node.init.maxRoot.l.top = el.node.init.maxRoot.l.top;
                        root.node.init.maxRoot.l.h   = maxh;
                    }

                    if(el.node.childrenRoot.unFlip.length > 0){
                        let rb = recursion(el.node.childrenRoot.unFlip,el);
                        // 最大高
                        maxh = rb.r.h;
                        el.node.init.maxRoot.r.ch = maxh;
                        h = el.node.init.size.h;
                        maxh = h<maxh?maxh:h;
                        el.node.init.maxRoot.r.h = maxh;

                        let mid = el.node.init.point.mid;
                        el.node.init.maxRoot.r.top = mid[1] - maxh/2;

                        root.node.init.maxRoot.r.top = el.node.init.maxRoot.r.top;
                        root.node.init.maxRoot.r.h = maxh;
                    }

                    __DB__.set('root',root);

                    return;
                }

                el.show = true;
                if(parent && !parent.root)el.flip = parent.flip;

                if(el.flip){
                    fn_left.call(_this,el);
                }
                else{
                    fn_right.call(_this,el);
                }
            })

            return max;
            
            function fn_left(item) {
                let init = item.node.init;
                let h = parseFloat(init.size.h.toFixed(2)) + __canvas__.space_y;
                // 如果没有同胞就减掉垂直间距
                if(parent&&parent.node.root&&parent.node.childrenRoot.flip.length === 1){
                    h = h - __canvas__.space_y;
                }
                else if(parent&&parent.node.children && parent.node.children.length === 1){
                    h = h - __canvas__.space_y;
                }

                if(item.node.children.length > 0){
                    let w1 = item.node.children[0].node.init.size.w + __canvas__.space_x;
                    item.node.children.forEach(el=>{
                        let w = el.node.init.size.w + __canvas__.space_x;
                        w1 = w1>w?w1:w;
                    });

                    max.l.w += w1;

                    let rb = recursion(item.node.children,item);
                    let maxh = rb.l.h;
                    init.max.ch = maxh;
                    maxh = h<maxh?maxh:h;
                    init.max.h = maxh;
                    max.l.h += maxh;
                    max.l.w += rb.l.w;
                    return;
                }

                init.max.h = h;
                init.max.ch = h;
                max.l.h += h;
            };

            function fn_right(item) {
                let init = item.node.init,
                    children = item.node.children;
                let h = parseFloat(init.size.h.toFixed(2)) + __canvas__.space_y;
                // 如果没有同胞就减掉垂直间距
                if(parent&&parent.root&&parent.node.childrenRoot.unFlip.length === 1){
                    h = h - __canvas__.space_y;
                }
                else if(parent&&parent.node.children && parent.node.children.length === 1){
                    h = h - __canvas__.space_y;
                }

                if(children.length > 0){
                    let w1 = children[0].node.init.size.w + __canvas__.space_x;
                    children.forEach(el=>{
                        let w = el.node.init.size.w + __canvas__.space_x;
                        w1 = w1>w?w1:w;
                    });
                    max.r.w += w1;

                    let rb = recursion(children,item);
                    let maxh = rb.r.h;
                    init.max.ch = maxh;

                    maxh = h<maxh?maxh:h;
                    init.max.h = maxh;
                    max.r.h += maxh;
                    return;
                }
                
                init.max.h      = h;
                init.max.ch     = h;
                max.r.h         += h;
            };
        }
    }

    // 解析节点 计算出节点的最大宽
    node_maxw(items){
        let _this = this;
        recursion(items);
        function recursion(items) {
            let maxw = 0;
            items.forEach(el=>{
                if(el.root){
                    let root = __DB__.get('root');
                    if(el.node.childrenRoot.flip.length > 0){
                        recursion(el.node.childrenRoot.flip);

                        let w1 = el.node.childrenRoot.flip[0].node.init.max.w;
                        el.node.childrenRoot.flip.forEach(item=>{
                            let w = item.node.init.max.w;
                            w1 = w1>w?w1:w;
                        });

                        el.node.init.maxRoot.l.w = w1;
                        root.node.init.maxRoot.l.w = w1;
                    }
                    if(el.node.childrenRoot.unFlip.length > 0){
                        recursion(el.node.childrenRoot.unFlip);

                        let w1 = el.node.childrenRoot.unFlip[0].node.init.max.w;
                        el.node.childrenRoot.unFlip.forEach(item=>{
                            let w = item.node.init.max.w;
                            w1 = w1>w?w1:w;
                        });

                        el.node.init.maxRoot.r.w = w1;
                        root.node.init.maxRoot.r.w = w1;
                    }
                }
                else{
                    el.show = true;
                    fn_child(el);
                }
            })

            return maxw;

            function fn_child(item) {
                let node = item.node;
                let w = node.init.size.w + __canvas__.space_x;
                w = w/__canvas__.scale;
                node.init.max.w = w;
                if(node.children.length > 0){
                    let rb = recursion(node.children);
                    let w1 = node.children[0].node.init.max.w;
                    node.children.forEach(el=>{
                        let w = el.node.init.max.w;
                        w1 = w1>w?w1:w;
                    });
                    maxw = w1 + w;
                    node.init.max.w = rb + w;
                }
                else{
                    maxw = maxw>w?maxw:w;
                }
            }
        }
    }

    // 解析节点 计算出需要的坐标
    node_poi(items){
        let _this = this;
        let $nEls = document.querySelectorAll('.xmd-node');
        recursion(items);
        return items;
        function recursion(items,parent){
            let myChild = [];
            items.forEach((el,i)=>{
                if(el.root){
                    if(el.node.childrenRoot.flip.length > 0){
                        myChild.push({children:el.node.childrenRoot.flip,parent:el,root:true});
                    }

                    if(el.node.childrenRoot.unFlip.length > 0){
                        myChild.push({children:el.node.childrenRoot.unFlip,parent:el,root:true});
                    }
                    return;
                }

                myChild.push({
                    children:el.node.children,
                    parent:el,
                    flip:el.flip,
                });

                if(el.flip){
                    fn_left(el,i);
                }
                else{
                    fn_right(el,i);
                }
            });

            if(myChild.length === 0)return;

            for(let el of myChild){
                recursion(el.children,el.parent);
            }

            function fn_left(item,index) {
                if(!parent)return;
                let init = item.node.init;
                let pMid = parent.node.init.point.mid;
                let pCh = parent.root?parent.node.init.maxRoot.l.ch:parent.node.init.max.ch;
                let ph = parent.root?parent.node.init.maxRoot.l.h:parent.node.init.max.h;
                let left = pMid[0] - parent.node.init.size.w/2 - __canvas__.space_x - init.size.w;
                let maxTop = pMid[1] - ph/2;

                if(index === 0){
                    let oo = init.max.h/2 - init.size.h/2;//如果自己小于后代的高度，减掉除自身外的高度除2来做为本节点的TOP
                    if(ph > pCh){maxTop = pMid[1] - pCh/2;}// 如果自己比后代的高度要高度，改变最大TOP
                    
                    let top  = maxTop + oo;

                    init.max.top   = maxTop;
                    init.poi.x     = left;
                    init.poi.y     = top;
                    $nEls[item.node.index].style.left = left + "px";
                    $nEls[item.node.index].style.top  = top  + "px";
                }
                else{
                    let top = items[index-1].node.init.max.top + items[index-1].node.init.max.h;
                    init.max.top = top;
                    top = top + (init.max.h/2 - init.size.h/2);
                    init.poi.x = left;
                    init.poi.y = top;
                    $nEls[item.node.index].style.left = left + "px";
                    $nEls[item.node.index].style.top  = top + "px";
                }
                
                
                let itemPoi = __tool__.idTrunPoi(item.id);
                init.point = itemPoi.point;
            };

            function fn_right(item,index) {
                
                if(!parent)return;
                let init    = item.node.init;
                let pMid    = parent.node.init.point.mid;
                let pCh     = parent.root?parent.node.init.maxRoot.r.ch:parent.node.init.max.ch;
                let ph      = parent.root?parent.node.init.maxRoot.r.h:parent.node.init.max.h;
                let left    = pMid[0] + parent.node.init.size.w/2 + __canvas__.space_x;
                let maxTop  = pMid[1] - ph/2;
                if(index === 0){
                    let oo = init.max.h/2 - init.size.h/2;//如果自己小于后代的高度，减掉除自身外的高度除2来做为本节点的TOP
                    if(ph > pCh){maxTop = pMid[1] - pCh/2;}// 如果自己比后代的高度要高度，改变最大TOP
                    
                    let top  = maxTop + oo;

                    init.max.top   = maxTop;
                    init.poi.x     = left;
                    init.poi.y     = top;
                    $nEls[item.node.index].style.left = left + "px";
                    $nEls[item.node.index].style.top  = top  + "px";
                }
                else{
                    let top = items[index-1].node.init.max.top + items[index-1].node.init.max.h;
                    init.max.top = top;
                    top = top + (init.max.h/2 - init.size.h/2);

                    init.poi.x = left;
                    init.poi.y = top;
                    $nEls[item.node.index].style.left = left + "px";
                    $nEls[item.node.index].style.top  = top + "px";
                }
                
                
                let itemPoi = __tool__.idTrunPoi(item.id);
                init.point = itemPoi.point;
            };
        }
    }

    // 子节点展开收起的图标
    node_pull(items){
        let $nEls = document.querySelectorAll('.xmd-node');
        recursion(items);
        return items;
        function recursion(items,parent){
            items.forEach((el,i)=>{
                if(el.root){
                    if(el.pull.l.has){
                        recursion(el.node.childrenRoot.flip);
                        el.pull.l.show = true;
                        pull_left(el);
                    }

                    if(el.pull.r.has){
                        recursion(el.node.childrenRoot.unFlip);
                        el.pull.r.show = true;
                        pull_right(el,true);
                    }
                    return;
                }

                el.node.children.length>0&&recursion(el.node.children);

                if(el.flip){
                    if(!el.pull.l.has)return;
                    el.pull.l.show = true;

                    pull_left(el);
                }
                else{
                    if(!el.pull.r.has)return;
                    el.pull.r.show = true;
                    pull_right(el);
                }
            });
        }

        function pull_left(el){
            let cls = el.pull.l.plus?"pull-plus":"pull-minus";
            for(let ee of $nEls){
                let id = ee.getAttribute("id");
                if(id === el.id){
                    for(let ef of ee.childNodes){
                        if(ef.classList[0] === 'xmd-node-pull'){
                            ef.childNodes[0].setAttribute('class',"pull-left");
                            ef.childNodes[0].classList.add(cls);
                            ef.childNodes[0].style.display = el.pull.l.show?"block":"none";
                            break;
                        }
                    }
                    break;
                }
            }
        }

        function pull_right(el,root){
            let cls = el.pull.r.plus?"pull-plus":"pull-minus";
            for(let ee of $nEls){
                let id = ee.getAttribute("id");
                if(id === el.id){
                    for(let ef of ee.childNodes){
                        if(ef.classList[0] === 'xmd-node-pull'){
                            let i = root?1:0;
                            ef.childNodes[i].setAttribute('class',"pull-right");
                            ef.childNodes[i].classList.add(cls);
                            ef.childNodes[i].style.display = el.pull.r.show?"block":"none";
                            break;
                        }
                    }
                    break;
                }
            }
        }
        
    }
}

let formate = new formateClass();
export default formate;